from pyglet.gl import *

from _global import enum
from vector import Vector3

class Primitive(object):
	Paint = enum("COLOR", "TEXTURE", "WIRE")
	
	def __init__(self, paint):
		self.paint = paint
	
	def build(self, d, args=[]):
		pass

class Cube(Primitive):
	"""Load a cube with textured sides"""
	
	def build(self, d, args=[]):
		super(Cube, self).build(d, args)
		
		if self.paint == Primitive.Paint.COLOR:
			glNewList(d.gl.id, GL_COMPILE)
			glColor3f(args[0][0], args[0][1], args[0][2])
			glBegin(GL_QUADS)
			glVertex3f(1., 1., 0.)	# Top Right Of The Quad (Top)
			glVertex3f(0., 1., 0.)	# Top Left Of The Quad (Top)
			glVertex3f(0., 1., 1.)	# Bottom Left Of The Quad (Top)
			glVertex3f(1., 1., 1.)	# Bottom Right Of The Quad (Top)
			glVertex3f(1., 0., 1.)	# Top Right Of The Quad (Bottom)
			glVertex3f(0., 0., 1.)	# Top Left Of The Quad (Bottom)
			glVertex3f(0., 0., 0.)	# Bottom Left Of The Quad (Bottom)
			glVertex3f(1., 0., 0.)	# Bottom Right Of The Quad (Bottom)
			glVertex3f(1., 1., 1.)	# Top Right Of The Quad (Front)
			glVertex3f(0., 1., 1.)	# Top Left Of The Quad (Front)
			glVertex3f(0., 0., 1.)	# Bottom Left Of The Quad (Front)
			glVertex3f(1., 0., 1.)	# Bottom Right Of The Quad (Front)
			glVertex3f(1., 0., 0.)	# Bottom Left Of The Quad (Back)
			glVertex3f(0., 0., 0.)	# Bottom Right Of The Quad (Back)
			glVertex3f(0., 1., 0.)	# Top Right Of The Quad (Back)
			glVertex3f(1., 1., 0.)	# Top Left Of The Quad (Back)
			glVertex3f(1., 1., 1.)	# Bottom Left Of The Quad (Right)
			glVertex3f(1., 1., 0.)	# Bottom Right Of The Quad (Right)
			glVertex3f(1., 0., 0.)	# Top Right Of The Quad (Right)
			glVertex3f(1., 0., 1.)	# Top Left Of The Quad (Right)
			glVertex3f(0., 1., 1.)	# Top Right Of The Quad (Left)
			glVertex3f(0., 1., 0.)	# Top Left Of The Quad (Left)
			glVertex3f(0., 0., 0.)	# Bottom Left Of The Quad (Left)
			glVertex3f(0., 0., 1.)	# Bottom Right Of The Quad (Left)
			glEnd()
			glEndList()
		elif self.paint == Primitive.Paint.TEXTURE:
			tca = self._getTexCoordArray(args)		#Array of texture coordinate tuples
			glNewList(d.gl.id, GL_COMPILE)
			#glTranslatef(-.5, -.5, -.5)
			glBegin(GL_QUADS)
			glTexCoord2f(tca[0][0], tca[0][1])
			glVertex3f(0., 1., 0.)	# Top Left Of The Quad (Top)
			glTexCoord2f(tca[1][0], tca[1][1])
			glVertex3f(1., 1., 0.)	# Top Right Of The Quad (Top)
			glTexCoord2f(tca[2][0], tca[2][1])
			glVertex3f(1., 1., 1.)	# Bottom Right Of The Quad (Top)
			glTexCoord2f(tca[3][0], tca[3][1])
			glVertex3f(0., 1., 1.)	# Bottom Left Of The Quad (Top)
			
			glTexCoord2f(tca[4][0], tca[4][1])
			glVertex3f(0., 0., 1.)	# Top Left Of The Quad (Bottom)
			glTexCoord2f(tca[5][0], tca[5][1])
			glVertex3f(1., 0., 1.)	# Top Right Of The Quad (Bottom)
			glTexCoord2f(tca[6][0], tca[6][1])
			glVertex3f(1., 0., 0.)	# Bottom Right Of The Quad (Bottom)
			glTexCoord2f(tca[7][0], tca[7][1])
			glVertex3f(0., 0., 0.)	# Bottom Left Of The Quad (Bottom)
			
			glTexCoord2f(tca[8][0], tca[8][1])
			glVertex3f(0., 1., 1.)	# Top Left Of The Quad (Front)
			glTexCoord2f(tca[9][0], tca[9][1])
			glVertex3f(1., 1., 1.)	# Top Right Of The Quad (Front)
			glTexCoord2f(tca[10][0], tca[10][1])
			glVertex3f(1., 0., 1.)	# Bottom Right Of The Quad (Front)
			glTexCoord2f(tca[11][0], tca[11][1])
			glVertex3f(0., 0., 1.)	# Bottom Left Of The Quad (Front)
			
			glTexCoord2f(tca[12][0], tca[12][1])
			glVertex3f(1., 1., 0.)	# Bottom Left Of The Quad (Back)
			glTexCoord2f(tca[13][0], tca[13][1])
			glVertex3f(0., 1., 0.)	# Bottom Right Of The Quad (Back)
			glTexCoord2f(tca[14][0], tca[14][1])
			glVertex3f(0., 0., 0.)	# Top Right Of The Quad (Back)
			glTexCoord2f(tca[15][0], tca[15][1])
			glVertex3f(1., 0., 0.)	# Top Left Of The Quad (Back)
			
			glTexCoord2f(tca[16][0], tca[16][1])
			glVertex3f(0., 1., 0.)	# Top Right Of The Quad (Left)
			glTexCoord2f(tca[17][0], tca[17][1])
			glVertex3f(0., 1., 1.)	# Top Left Of The Quad (Left)
			glTexCoord2f(tca[18][0], tca[18][1])
			glVertex3f(0., 0., 1.)	# Bottom Left Of The Quad (Left)
			glTexCoord2f(tca[19][0], tca[19][1])
			glVertex3f(0., 0., 0.)	# Bottom Right Of The Quad (Left)
			
			glTexCoord2f(tca[20][0], tca[20][1])
			glVertex3f(1., 1., 1.)	# Bottom Left Of The Quad (Right)
			glTexCoord2f(tca[21][0], tca[21][1])
			glVertex3f(1., 1., 0.)	# Bottom Right Of The Quad (Right)
			glTexCoord2f(tca[22][0], tca[22][1])
			glVertex3f(1., 0., 0.)	# Top Right Of The Quad (Right)
			glTexCoord2f(tca[23][0], tca[23][1])
			glVertex3f(1., 0., 1.)	# Top Left Of The Quad (Right)
			glEnd()
			#glTranslatef(.5, .5, .5)
			glEndList()
		
		if d.coll:
			d.coll.box.offset = Vector3(0, 1, 0)
			d.coll.box.size = Vector3(1, 1, 1)
	
	def _getTexCoordArray(self, args):
		l = len(args)
		if l > 1:
			if l == 2:		#Same texture for all 6 sides
				if len(args[0].coord) >= args[1] + 4:
					sq1 = args[0].coord[args[1]*4:args[1]*4+4]
					return sq1 * 6
			elif l == 4:	#One texture for each pair of faces per axis (x,y,z)
				sq1 = args[0].coord[args[1]*4:args[1]*4+4]
				sq2 = args[0].coord[args[2]*4:args[2]*4+4]
				sq3 = args[0].coord[args[3]*4:args[3]*4+4]
				return sq1*2 + sq2*2 + sq3*2
			elif l == 7:	#One texture per face (u,d,l,r,f,b)
				sq1 = args[0].coord[args[1]*4:args[1]*4+4]
				sq2 = args[0].coord[args[2]*4:args[2]*4+4]
				sq3 = args[0].coord[args[3]*4:args[3]*4+4]
				sq4 = args[0].coord[args[4]*4:args[4]*4+4]
				sq5 = args[0].coord[args[5]*4:args[5]*4+4]
				sq6 = args[0].coord[args[6]*4:args[6]*4+4]
				return sq1 + sq2 + sq3 + sq4 + sq5 + sq6
		raise Exception("Incorrect number of texture arguments:", l)

class Sphere(Primitive):
	"""Load a sphere!"""
	
	def build(self, d, args=[]):
		super(Sphere, self).build(d, args)
		
		glNewList(d.gl.id, GL_COMPILE)
		q = gluNewQuadric()
		gluQuadricNormals(q, GLU_SMOOTH)
		gluQuadricTexture(q, GL_TRUE)
		if self.paint == Primitive.Paint.COLOR and len(args):
			glColor3f(args[0].x, args[0].y, args[0].z)
		gluSphere(q, .5, 12, 12)
		glEndList()
		
		if d.coll:
			d.coll.box.offset = Vector3(.5, .5, .5)
			d.coll.box.size = Vector3(1, 1, 1)
		